home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 08 - 1992 / 08.04 Aug 92 / Hello TCL World / oopsDebug.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-23  |  5.0 KB  |  222 lines  |  [TEXT/KAHL]

  1. #define DEBUG 1
  2. /*
  3.  * oopsDebug.c
  4.  * This is a modified version of the Think C oops (object support)
  5.  * module that executes a Debug trap if you try to dispatch on a
  6.  * NULL instance variable. It should only be used if you are running
  7.  * under the Think C debugger or have a hardware debugger (MacsBug
  8.  * or TMON) installed. It would be useful to extend this so it
  9.  * printed the calling chain when the trap occurs -- this would
  10.  * permit capturing debug information even in production software.
  11.  *
  12.  * If you continue after the debug trap occurs, the function will
  13.  * return to its caller. This is only to allow you to evaluate
  14.  * variables in the caller's context -- you shouldn't assume
  15.  * that the program may continue without further failure.
  16.  *
  17.  * Symantec does not endorse or support these changes to oops.c.
  18.  * The object dispatch mechanism is not documented.  It can and
  19.  * will change in future versions of Think C.
  20.  *
  21.  * This change to oops.c will not work with future versions of Think C.
  22.  *
  23.  * The modifications are copyright 1991 Martin Minow. They may
  24.  * be used and distributed by any individual or organization
  25.  * under terms of their license with Symantec Corporation.
  26.  */
  27. /*
  28.  *  oops.c
  29.  *
  30.  *  Copyright (c) 1989 Symantec Corporation.  All rights reserved.
  31.  *
  32.  */
  33. #include "oops.h"
  34.  
  35. #ifndef DEBUG
  36. #define DEBUG    0
  37. #endif
  38.  
  39. #ifdef DIRECT
  40. #define member    memberD
  41. #define bless    blessD
  42. #define __msg    __msgD
  43. #else
  44. #define INDIRECT
  45. #endif
  46.  
  47. void __msg(void);
  48.  
  49.  
  50. /*
  51.  *  new - allocate a new object
  52.  *
  53.  *  The new object is returned.  (This implementation initializes the
  54.  *  object to all-bits-zero, but it may be unwise to rely on this.)
  55.  *
  56.  *  This routine is for use with indirect classes.  There is no
  57.  *  corresponding facility for direct classes.
  58.  *
  59.  *  If an object is created other than by calling this routine, it
  60.  *  must be marked as belonging to its class by calling "bless" or
  61.  *  "blessD".  (Since allocation of direct objects is the programmer's
  62.  *  responsibility, "blessD" must always be called.)
  63.  *
  64.  */
  65.  
  66. #ifdef INDIRECT
  67. void *
  68. new(class)
  69. void *class;
  70. {
  71.     asm {
  72.         moveq    #0,d0
  73.         movea.l    class,a1
  74.         move.w    (a1),d0                ;  D0.L = class size
  75.         _NewHandle  CLEAR
  76.         move.l    a0,d0
  77.         beq.s    @1
  78.         suba.l    a5,a1                ;  A1.W = class ID
  79.         movea.l    (a0),a0                ;  <<indirect>>
  80.         move.w    a1,(a0)
  81. @1    }
  82. }
  83. #endif INDIRECT
  84.  
  85.  
  86. /*
  87.  *  delete - free an object
  88.  *
  89.  *  This routine is for use with indirect classes.  There is no
  90.  *  corresponding facility for direct classes.
  91.  *
  92.  */
  93.  
  94. #ifdef INDIRECT
  95. void
  96. delete(obj)
  97. void *obj;
  98. {
  99.     asm {
  100.         move.l    obj,d0
  101.         beq.s    @1
  102.         movea.l    d0,a0
  103.         _DisposHandle
  104. @1    }
  105. }
  106. #endif INDIRECT
  107.  
  108.  
  109. /*
  110.  *  member, memberD - test whether an object is a member of a class
  111.  *
  112.  *  A non-zero value is returned if the object's class, or any of its
  113.  *  ancestors, is equal to the given class.
  114.  *
  115.  *  "member" is for use only with indirect classes, and "memberD" is
  116.  *  for use only with direct classes.  Do not attempt to use either
  117.  *  function to test whether a direct object is a member of an indirect
  118.  *  class, or whether an indirect object is a member of a direct class.
  119.  *  (Of course, in these cases, the answer is "no"!)
  120.  *
  121.  */
  122. #if DEBUG
  123. static char    DebugMember[]    = "\pNULL Member";
  124. #endif
  125.  
  126. int
  127. member(obj, class)
  128. void *obj, *class;
  129. {
  130.     asm {
  131.         move.l    class,d1
  132.         sub.l    a5,d1                ;  D1.W = target class ID
  133.         movea.l    obj,a1
  134. #if DEBUG
  135.         move.l    a1,d0                ; Copy to set condition codes
  136.         bne.s    @3                    ; Ok
  137.         pea        DebugMember
  138.         DebugStr
  139.         bra.s    @2                    ; Return to the scene of the crime
  140. @3
  141. #endif
  142. #ifdef INDIRECT
  143.         movea.l    (a1),a1                ;  <<indirect>>
  144. #endif INDIRECT
  145.         move.w    (a1),d0                ;  D0.W = class ID
  146. @1        cmp.w    d0,d1
  147.         beq.s    @2
  148.         lea        2(a5,d0.w),a1        ;  A1 ==> class record + 2
  149.         move.w    (a1)+,d0            ;  D0.W = #methods - 1
  150.         add.w    d0,d0
  151.         add.w    d0,d0
  152.         move.w    4(a1,d0.w),d0        ;  D0.W = superclass ID
  153.         bne.s    @1
  154. @2    }
  155. }
  156.  
  157.  
  158. /*
  159.  *  bless, blessD - mark an object as being of a particular class
  160.  *
  161.  *  If an object is created other than by "new", this routine must
  162.  *  be called to mark it as a member of its class.
  163.  *
  164.  *  Do not use this routine to change an object's class!
  165.  *
  166.  */
  167.  
  168. void
  169. bless(obj, class)
  170. void *obj, *class;
  171. {
  172.     asm {
  173.         move.l    class,d1
  174.         sub.l    a5,d1                ;  D1.W = class ID
  175.         movea.l    obj,a1
  176. #ifdef INDIRECT
  177.         movea.l    (a1),a1                ;  <<indirect>>
  178. #endif INDIRECT
  179.         move.w    d1,(a1)
  180.     }
  181. }
  182.  
  183.  
  184. /*
  185.  *  __msg, __msgD - message dispatcher
  186.  *
  187.  *  The dispatcher is called only from code generated by the compiler.
  188.  *
  189.  */
  190. #if DEBUG
  191. static char DebugMsg[]        = "\pNULL Method";
  192. #endif
  193.  
  194. void
  195. __msg()
  196. {
  197.     asm {
  198.         movea.l    4(sp),a1
  199.         move.w    -(a1),d2            ;  D2.W = message ID
  200.         movea.l    8(sp),a1
  201. #if DEBUG
  202.         move.l    a1,d0                ; Copy to set condition codes
  203.         bne.s    @3                    ; Ok
  204.         pea        DebugMsg
  205.         DebugStr                    ; Oops
  206.         bra.s    @4                    ; Return to the scene of the crime
  207. @3
  208. #endif
  209. #ifdef INDIRECT
  210.         movea.l    (a1),a1                ;  <<indirect>>
  211. #endif INDIRECT
  212. @1        move.w    (a1),d0
  213.         lea        2(a5,d0.w),a1        ;  A1 ==> class record + 2
  214.         move.w    (a1)+,d0            ;  D0.W = #methods - 1
  215. @2        move.w    (a1)+,d1            ;  D1.W = method ID
  216.         cmp.w    (a1)+,d2
  217.         dbeq    d0,@2
  218.         bne.s    @1                    ;  not found - search superclass
  219.         lea        0(a5,d1.w),a0        ;  A0 ==> method
  220. @4    }
  221. }
  222.